package com.fz.us.admin.company.service.impl;

import com.fz.us.admin.base.bean.BaseEnumManager;
import com.fz.us.admin.base.bean.Result;
import com.fz.us.admin.base.dao.BaseDao;
import com.fz.us.admin.base.service.impl.BaseServiceImpl;
import com.fz.us.admin.company.entity.Company;
import com.fz.us.admin.company.entity.Department;
import com.fz.us.admin.company.entity.Post;
import com.fz.us.admin.company.entity.User;
import com.fz.us.admin.company.service.DepartmentService;
import com.fz.us.admin.company.dao.DepartmentDao;
import com.fz.us.admin.company.service.DutyService;
import com.fz.us.admin.company.service.PowerService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;

/**
 * Service实现类 - Department
 * ============================================================================
 * 版权所有 2016 。
 *
 * @author fallenpanda
 * @version 1.0 2016-08-02 。
 * ============================================================================
 */
@Service
public class DepartmentServiceImpl extends BaseServiceImpl<Department, String> implements DepartmentService {

    @Resource
    private DepartmentDao departmentDao;
    @Override
    public BaseDao<Department, String> getBaseDao() {
        return departmentDao;
    }

    @Resource
    private PowerService powerService;
    @Resource
    private DutyService dutyService;

    @Override
    public List<Department> getAllDepartments(Company company) {
        return departmentDao.getAllDepartments(company);
    }

    @Override
    public List<Department> getRootDepartments(Company company) {
        return departmentDao.getRootDepartments(company);
    }

    @Override
    public List<Department> getDepartments(Company company, Department department) {
        return departmentDao.getDepartments(company, department);
    }

    @Override
    public boolean isParentDepartment(Department department) {
        return departmentDao.isParentDepartment(department);
    }

    @Override
    public Result saveEntity(Department entity) {


        if (entity.getLevel() > 7) {
            resultService.fail("部门层级超过限制");
        }
        Result rs = super.saveEntity(entity);
        // 计算 path
        updatePath(entity);
        update(entity);
        return rs;
    }

    @Override
    public Result createEntity(User user, Department department) {
        Assert.notNull(user, "user is required");
        Assert.notNull(department, "department is required");

        // 设置所属企业
        department.setCompany(user.getCompany());

        Result result = saveEntity(department);

        if (result.isOK()) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("id", department.getId());
            map.put("parentId", department.getParent()==null?"":department.getParent().getId());

            return resultService.successWithData(map);
        } else {
            return result;
        }
    }

    @Override
    public Result updateEntity(User user, String keyId, Department department) {
        Assert.notNull(user, "user is required");
        Assert.hasText(keyId, "keyId is required");
        Assert.notNull(department, "department is required");

        Department departmentTemp = get(keyId);
        departmentTemp.setName(department.getName());
        departmentTemp.setSortNo(department.getSortNo());
        departmentTemp.setCode(department.getCode());
        departmentTemp.setDescription(department.getDescription());

        update(departmentTemp);

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", departmentTemp.getId());
        map.put("parentId", departmentTemp.getParent()==null?"":department.getParent().getId());

        return resultService.successWithData(map);
    }

    @Override
    public Result methodEntity(User user, String method, String keyId) {
        Assert.notNull(user, "user is required");
        Assert.hasText(method, "method is required");
        Assert.hasText(keyId, "keyId is required");

        Department department = get(keyId);
        if (department != null) {
            if (StringUtils.equals("Delete", method)) {// 删除
                // 是否存在职权配置
                if (powerService.hasDepartment(department)) {
                    return resultService.fail("已配置部门职权,请先删除部门职权");
                }
                // 是否存在人员分配
                if (dutyService.hasDepartment(department)) {
                    return resultService.fail("已配置部门人员,请先删除部门成员");
                }
                // 是否存在下级部门
                if (isParentDepartment(department)) {
                    return resultService.fail("存在下级部门,请先删除");
                }

                Result result = methodEntity(BaseEnumManager.MethodEnum.Delete, keyId);

                Map<String, Object> map = new HashMap<String, Object>();
                map.put("id", department.getId());
                map.put("parentId", department.getParent()==null?"":department.getParent().getId());
                result.setData(map);

                return result;
            }
        }

        return resultService.fail();
    }

    @Override
    public Result dropInnerEntity(User user, String keyId, String targetId) {
        Assert.notNull(user, "user is required");
        Assert.hasText(keyId, "keyId is required");

        Department department = get(keyId);
        Department targetDepartment = null;
        if (StringUtils.isNotEmpty(targetId))
            targetDepartment = get(targetId);
        if (department!=null) {
            department.setParent(targetDepartment);
            // 计算 path
            updatePath(department);
            // 保存更新
            update(department);
            // 更新下级部门
            updateChildrenPath(department);

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("id", keyId);
            map.put("parentId", targetId);

            return resultService.successWithData(map);
        }

        return resultService.fail();
    }

    /**
     * 迭代
     *
     * @param department
     */
    private void updateChildrenPath(Department department) {
        List<Department> children = getDepartments(department.getCompany(), department);
        if (children!=null && children.size()>0) {
            for (Department child : children) {
                // 计算 path
                updatePath(child);
                update(child);
                // 迭代下级部门
                updateChildrenPath(child);
            }
        }
    }

    /**
     * 更新 path level
     *
     * @param department
     */
    private void updatePath(Department department) {
        // 计算 path
        if (department.getParent() != null) {
            Department parent = department.getParent();
            department.setPath(parent.getPath() + Department.PATH_SEPARATOR + department.getId());
        } else {
            department.setPath(department.getId());
        }
        // 计算 level
        int level = 0;
        if (StringUtils.isNotEmpty(department.getPath())) {
            level = StringUtils.split(department.getPath(), Department.PATH_SEPARATOR).length;
        }
        department.setLevel(level);
    }

    @Override
    public Map<String, Object> getListMap(Department department) {
        Map<String, Object> map = new HashMap<String, Object>();

        map.put("id", StringUtils.isEmpty(department.getId())?"":department.getId());
        map.put("name", StringUtils.isEmpty(department.getName())?"":department.getName());
        map.put("pinYinHead", StringUtils.isEmpty(department.getPinYinHead())?"":department.getPinYinHead().toLowerCase());
        map.put("pinYin", StringUtils.isEmpty(department.getPinYin())?"":department.getPinYin());

        map.put("sortNo", department.getSortNo());
        map.put("code", StringUtils.isEmpty(department.getCode())?"":department.getCode());
        map.put("description", StringUtils.isEmpty(department.getDescription())?"":department.getDescription());

        map.put("parentId", "");
        map.put("parentName", "");
        if (department.getParent() != null) {
            Department parent = department.getParent();
            map.put("parentId", StringUtils.isEmpty(parent.getId())?"":parent.getId());
            map.put("parentName", StringUtils.isEmpty(parent.getName())?"":parent.getName());
        }

        // other
        map.put("state", department.getState()==null?"":department.getState().name());

        return map;
    }

    @Override
    public Map<String, Object> getDetailMap(Department department) {
        return getListMap(department);
    }

    @Override
    public Map<String, Object> getTreeMap(Department department) {
        Map<String, Object> map = new HashMap<String, Object>();

        map.put("id", StringUtils.isEmpty(department.getId())?"":department.getId());
        map.put("name", StringUtils.isEmpty(department.getName())?"":department.getName());

        map.put("isParent", isParentDepartment(department));

        return map;
    }


    @Override
    public List<Map<String, Object>> getTreeMapList(Company company) {
        return recursivTreeMapList(getAllDepartments(company), null);
    }

    /**
     * 递归部门 返回 Tree结构
     *
     * @param departmentList
     * @param parent
     * @return
     */
    private List<Map<String, Object>> recursivTreeMapList(List<Department> departmentList, Department parent) {
        List<Map<String, Object>> departmentTreeList = new ArrayList<Map<String, Object>>();
        if (departmentList != null && departmentList.size() > 0) {
            for (Department department : departmentList) {
                Department parentDepartment = department.getParent();
                if ((parent == null && parentDepartment == null) || (parent != null && parentDepartment != null && parent.equals(parentDepartment))) {
                    Map<String, Object> tempMap = new HashMap<String, Object>();
                    tempMap.put("id", department.getId());
                    tempMap.put("name", department.getName());
                    tempMap.put("children", recursivTreeMapList(departmentList, department));
                    departmentTreeList.add(tempMap);
                }
            }
        }
        return departmentTreeList;
    }

    @Override
    public List<Department> getDepartments(String name) {
        return departmentDao.getDepartments(name);
    }

    @Override
    public Set<Department> getChildDepart(Department department, Set<Department> set) {
        Set<Department> departmentChildren=null;
        if (department != null) {
            departmentChildren = department.getChildren();
            set.add(department);
        }else{
            return set;
        }

        if(departmentChildren!=null){
            for(Department depart:departmentChildren){
                getChildDepart(depart,set);
            }
        }else{
            return set;
        }
        return set;
    }

}
